﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using DataCenter.Share;

namespace DataCenter.Interface.Model
{
    public class EntityCollection
    {
        public EntityCollection(SqlCommand command)
        {
            this._Command = command;
        }
        private SqlCommand _Command;

        private int virtualObjectCount;
        public Dictionary<int, ObjectEntity> DictObject;
        public Dictionary<int, ComponentEntity> DictComponent;
        public int VirtualObjectCount
        {
            get { return virtualObjectCount; }
        }

        public ObjectEntity GetObject(int objectId)
        {
            if (DictObject.ContainsKey(objectId))
                return DictObject[objectId];
            return null;
        }

        public ComponentEntity GetComponent(int componentId)
        {
            if (DictComponent.ContainsKey(componentId))
                return DictComponent[componentId];
            return null;
        }

        public void Initialize(string objectIds)
        {
            InitObject(objectIds, false);
            InitComputeObjects();

            List<int> idList = new List<int>();       
            foreach (ObjectEntity objectEntity in DictObject.Values)
            {                
                if (objectEntity.CanImport)
                {
                    if (idList.BinarySearch(objectEntity.BindingSourceId) < 0)
                    {
                        idList.Add(objectEntity.BindingSourceId);
                    }
                    if (idList.BinarySearch(objectEntity.BindingAdapterId) < 0)
                    {
                        idList.Add(objectEntity.BindingAdapterId);
                    }
                }
                if (objectEntity.CanProcess)
                {
                    if (idList.BinarySearch(objectEntity.BindingProcessorId) < 0)
                    {
                        idList.Add(objectEntity.BindingProcessorId);
                    }
                }
                if (objectEntity.IsVirtual)
                {
                    if (objectEntity.CanCalculate)
                    {
                        if (idList.BinarySearch(objectEntity.BindingCalculatorId) < 0)
                        {
                            idList.Add(objectEntity.BindingCalculatorId);
                        }
                    }
                }
            }

            if (idList.Count > 0)
            {
                string componentIds = Utils.ArrayToString(idList.ToArray());
                DictComponent = ComponentEntity.Search(_Command, componentIds);
            }
        }

        private void InitComputeObjects()
        {
            List<int> idList = new List<int>();
            foreach (ObjectEntity objectEntity in DictObject.Values)
            {
                if (objectEntity.IsVirtual)
                {
                    int[] idArray = objectEntity.GetComputeObjectIds();
                    foreach (int objectId in idArray)
                    {
                        if (!DictObject.ContainsKey(objectId))
                        {
                            if (idList.BinarySearch(objectId) < 0)
                            {
                                idList.Add(objectId);
                            }
                        }
                        else
                        {
                            DictObject[objectId].IsComputeObject = true;
                        }
                    }
                    virtualObjectCount += 1;
                }
            }

            if (idList.Count > 0)
            {
                string objectIds = Utils.ArrayToString(idList.ToArray());
                InitObject(objectIds, true);
            }
        }

        public string GetObjectIds(bool includeVirtualObjects)
        {
            StringBuilder idBuilder = new StringBuilder();
            foreach (ObjectEntity entityObject in DictObject.Values)
            {
                if (!includeVirtualObjects)
                {
                    if (entityObject.IsVirtual)
                        continue;
                }                

                idBuilder.Append(",");
                idBuilder.Append(entityObject.ObjectId);
            }
            if (idBuilder.Length > 0)
                return idBuilder.ToString().Substring(1);
            return "";
        }

        public string GetComputeObjectIds()
        {
            StringBuilder idBuilder = new StringBuilder();
            foreach (ObjectEntity entityObject in DictObject.Values)
            {
                if (entityObject.IsVirtual || entityObject.IsComputeObject)
                {
                    idBuilder.Append(",");
                    idBuilder.Append(entityObject.ObjectId);
                }
            }
            if (idBuilder.Length > 0)
                return idBuilder.ToString().Substring(1);
            return "";
        }

        private void InitObject(string objectIds, bool isComputeObject)
        {
            string commandString = "SELECT * FROM [Object] WHERE 1 = 1";
            if (!string.IsNullOrEmpty(objectIds)) commandString += " AND ObjectId IN (" + objectIds + ")";
            commandString += " ORDER BY ObjectId, ObjectType";
            _Command.CommandText = commandString;
            _Command.CommandType = CommandType.Text;

            if (DictObject == null)
                DictObject = new Dictionary<int, ObjectEntity>();
            using (SqlDataReader reader = _Command.ExecuteReader())
            {
                while (reader.Read())
                {
                    ObjectEntity objectEntity = new ObjectEntity();
                    objectEntity.Build(reader);
                    objectEntity.IsComputeObject = isComputeObject;
                    if (!DictObject.ContainsKey(objectEntity.ObjectId))
                        DictObject.Add(objectEntity.ObjectId, objectEntity);
                }
            }
        }        
    }
}
